package com.bluexmicro.ota2.ui.screen.dfu

import android.bluetooth.le.ScanResult
import android.content.Context
import android.util.Log
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.bluexmicro.ota.FirmwareHelper
import com.bluexmicro.ota.dfu.DfuProcess
import com.bluexmicro.ota.dfu.ExitAction
import com.bluexmicro.ota.dfu.FirmwareBean
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.catch
import kotlinx.coroutines.launch
import kotlinx.coroutines.withTimeout
import java.io.File
import kotlin.Exception

data class TimeConsuming(
    val setup: Long,
    val update: Long
)


class DfuViewModel : ViewModel() {

    val items = mutableStateOf<List<FirmwareBean>>(emptyList())
    val target = mutableStateOf<ScanResult?>(null)
    val progress = mutableStateOf(-1f)

    val updating = derivedStateOf {
        progress.value >= 0f
    }

    val canUpdate = derivedStateOf {
        items.value.isNotEmpty() && target.value != null && updating.value.not()
    }

    //失败
    val error = mutableStateOf<String?>(null)

    //成功
    val timeConsuming = mutableStateOf<TimeConsuming?>(null)

    private var cacheZip: File? = null
    fun onFileSelected(context: Context, zip: File) = viewModelScope.launch(Dispatchers.IO) {
        try {
            items.value = FirmwareHelper.unzipToFirmwares(context, zip)
            cacheZip = zip
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }

    fun onDeviceSelected(scanResult: ScanResult) {
        target.value = scanResult
    }


    fun startUpdate(context: Context) = viewModelScope.launch(Dispatchers.Default) {
        error.value = null
        var setupTimeConsuming = 0L
        var updateTimeConsuming: Long
        val dfu = DfuProcess()
        val process = try {
            progress.value = 0f
            val anchor1 = System.currentTimeMillis()
            dfu.initialize(context, target.value!!.device).apply {
                setupTimeConsuming = System.currentTimeMillis() - anchor1
            }
        } catch (e: Exception) {
            progress.value = -1f
            error.value = e.message ?: "Unknown Error"
            null
        }
        process?.apply {
            val anchor2 = System.currentTimeMillis()
            update(cacheZip!!, ExitAction.RebootEnterApp)
                .catch {
                    error.value = it.message ?: "Unknown Error"
                    progress.value = -1f
                }.collect {
                    progress.value = it
                }
            updateTimeConsuming = System.currentTimeMillis() - anchor2
            timeConsuming.value = TimeConsuming(setupTimeConsuming, updateTimeConsuming)
            delay(500)
            progress.value = -1f
        }
    }
}